package com.demo.starter.service.impl;

import com.demo.starter.domain.JobDO;
import com.demo.starter.domain.dto.JobInputDTO;
import com.demo.starter.domain.dto.JobOutputDTO;
import com.demo.starter.exception.JobServiceException;
import com.demo.starter.repository.extend.JobExtendMapper;
import com.demo.starter.service.IQuartzService;
import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service("quartzService")
public class QuartzServiceImpl implements IQuartzService {

    private final static Logger logger = LoggerFactory.getLogger(QuartzServiceImpl.class);

    @Autowired
    @Qualifier("Scheduler")
    private Scheduler scheduler;

    @Autowired
    private JobExtendMapper jobMapper;

    @Override
    public void add(JobInputDTO dto) throws JobServiceException {
        try {
            Class cls = Class.forName(dto.getJobClassName());
            cls.newInstance();
            //构建job信息
            final String jobName = dto.getJobName();
            final String groupName = dto.getGroupName();
            JobDetail job = JobBuilder.newJob(cls).withIdentity(jobName, groupName)
                    .withDescription(dto.getDescp()).build();
            // 触发时间点
            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(dto.getCronExpression());
            Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger" + jobName, groupName)
                    .startNow().withSchedule(cronScheduleBuilder).build();
            //交由Scheduler安排触发
            scheduler.scheduleJob(job, trigger);
            logger.info("Job add success: jobName={}, groupName={}", dto.getJobName(), dto.getGroupName());
        } catch (ClassNotFoundException | IllegalAccessException | InstantiationException | SchedulerException e) {
            final String msg = "Job add failed:";
            logger.error("Job add failed: jobName={}, groupName={}", dto.getJobName(), dto.getGroupName());
            logger.error("" + e);
            throw new JobServiceException(msg, e);
        }
    }

    @Override
    public void trigger(String jobName, String groupName) throws JobServiceException {
        try {
            JobKey key = new JobKey(jobName, groupName);
            scheduler.triggerJob(key);
            logger.info("Job trigger success: jobName={}, groupName={}", jobName, groupName);
        } catch (SchedulerException e) {
            final String msg = "Job trigger failed:";
            logger.error("Job trigger failed:: jobName={}, groupName={}", jobName, groupName);
            logger.error("" + e);
            throw new JobServiceException(msg, e);
        }
    }

    @Override
    public void pause(String jobName, String groupName) throws JobServiceException {
        try {
            JobKey key = new JobKey(jobName, groupName);
            scheduler.pauseJob(key);
            logger.info("Job pause success: jobName={}, groupName={}", jobName, groupName);
        } catch (SchedulerException e) {
            final String msg = "Job pause failed";
            logger.error("Job pause failed: jobName={}, groupName={}", jobName, groupName);
            logger.error("" + e);
            throw new JobServiceException(msg, e);
        }
    }

    @Override
    public void resume(String jobName, String groupName) throws JobServiceException {
        try {
            JobKey key = new JobKey(jobName, groupName);
            scheduler.resumeJob(key);
            logger.info("Job resume success: jobName={}, groupName={}", jobName, groupName);
        } catch (SchedulerException e) {
            final String msg = "Job resume failed";
            logger.error("Job resume failed: jobName={}, groupName={}", jobName, groupName);
            logger.error("" + e);
            throw new JobServiceException(msg, e);
        }
    }

    @Override
    public void remove(String jobName, String groupName) throws JobServiceException {
        try {
            TriggerKey triggerKey = TriggerKey.triggerKey(jobName, groupName);
            // 停止触发器
            scheduler.pauseTrigger(triggerKey);
            // 移除触发器
            scheduler.unscheduleJob(triggerKey);
            // 删除任务
            scheduler.deleteJob(JobKey.jobKey(jobName, groupName));
            logger.info("Job remove success: jobName={}, groupName={}", jobName, groupName);
        } catch (Exception e) {
            final String msg = "Job remove failed:";
            logger.error("Job remove failed: jobName={}, groupName={}", jobName, groupName);
            logger.error("" + e);
            throw new JobServiceException(msg, e);
        }
    }

    @Override
    public List<JobOutputDTO> list(String jobName) {
        List<JobOutputDTO> result = new ArrayList<>();
        final List<JobDO> quartzEntities = jobMapper.selectList(jobName);
        if (CollectionUtils.isEmpty(quartzEntities)) {
            return result;
        }
        return quartzEntities.stream().map(this::wrapDTO).collect(Collectors.toList());
    }

    /**
     * 封装DTO
     *
     * @param jobDO
     * @return
     */
    private JobOutputDTO wrapDTO(JobDO jobDO) {
        return new JobOutputDTO(jobDO);
    }

    @Override
    public Long count() {
        return jobMapper.count();
    }
}
